package org.colafries.admin.querybuilder.customQuery;

import org.colafries.admin.entity.vo.ColumnRspVO;
import org.colafries.admin.entity.domain.DataModelConfig;
import org.colafries.admin.entity.vo.CustomQueryReqVO;
import org.colafries.admin.exceptions.ServiceException;
import org.colafries.admin.querybuilder.entity.CustomQueryParamContext;
import org.colafries.admin.querybuilder.utils.SqlSegmentBuilderUtil;
import org.colafries.common.enums.ColumnTypeEnum;
import org.colafries.common.enums.Flag;
import org.colafries.admin.entity.domain.QueryParam;
import org.colafries.admin.querybuilder.entity.CustomQuerySqlBuildContext;
import org.apache.commons.collections4.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * @author colafries
 * @version v1.0
 * @ClassName DimensionBuilder
 * @Description
 * @date Created in 2024/5/15
 **/
public class CustomQueryDimensionBuilder implements CustomQuerySqlSegmentBuilder {
    /**
     * @param customQueryParam
     * @return void
     * @author colafries
     * @Date 2024/5/16
     */
    @Override
    public void buildQueryParma(CustomQueryReqVO.CustomQueryParam customQueryParam,
                                CustomQueryParamContext customQueryParamContext) {
        // 如果查询参数为空 or 模型配置为空 or 维度、度量都为空
        // 查询所有维度、度量
        if (Optional.ofNullable(customQueryParam)
                .map(queryParam -> CollectionUtils.isEmpty(queryParam.getDimensions())
                        && CollectionUtils.isEmpty(queryParam.getMeasures())
                )
                .orElse(true)) {
            // dimension
            List<DataModelConfig> dimensionConfigs = customQueryParamContext.getDataModelListMap()
                    .get(ColumnTypeEnum.DIMENSION.getValue());
            dimensionConfigs.forEach(config -> customQueryParamContext.getDimensions().add(createDimension(config)));
        }

        // Dimension
        Optional.ofNullable(customQueryParam)
                .map(CustomQueryReqVO.CustomQueryParam::getDimensions)
                .ifPresent(dimensions -> {
                    dimensions.forEach(dimensionFieldHash -> {
                        customQueryParamContext.getDimensions().add(
                                Optional.ofNullable(customQueryParamContext.getDataModelConfigMap().get(dimensionFieldHash))
                                        .map(this::createDimension)
                                        .orElseThrow(() -> new ServiceException("维度不存在 fieldHash：" + dimensionFieldHash))
                        );
                    });
                });
    }

    /**
     * 构建 QueryParam.Dimension
     *
     * @param config
     * @return org..colafries.common.model.metadata.QueryParam.Dimension
     * @author colafries
     * @Date 2024/5/16
     */
    private QueryParam.Dimension createDimension(DataModelConfig config) {
        return QueryParam.Dimension.builder()
                .field(config.getField())
                .fieldHash(config.getFieldHash())
                .expression(config.getExpression())
                .calculatedFlag(config.getCalculatedFlag())
                .build();
    }

    /**
     * SelectPart:selectColumns、groupByColumns、havingConditions
     *
     * @param queryParam
     * @param customQuerySqlQueryContext
     * @return void
     * @author colafries
     * @Date 2024/5/16
     */
    @Override
    public void buildQuery(QueryParam queryParam, CustomQuerySqlBuildContext customQuerySqlQueryContext) {
        // dimensions
        List<QueryParam.Dimension> dimensions = Optional.of(queryParam).map(QueryParam::getDimensions)
                .orElse(Collections.emptyList());

        dimensions.forEach(dimension -> {
            String fieldHash = dimension.getFieldHash();
            String field = dimension.getField();
            ColumnTypeEnum columnType = ColumnTypeEnum.DIMENSION;
            String tableHash = dimension.getTableHash();
            String expression = dimension.getExpression();
            // 构建表达式
            if (Flag.YES == dimension.getCalculatedFlag()) {
                expression = SqlSegmentBuilderUtil.convertExpression(expression, customQuerySqlQueryContext.getFildExpMap());
            } else {
                ColumnRspVO customTableSchema = customQuerySqlQueryContext.getCustomTableSchemaMap().get(dimension.getFieldHash());
                tableHash = customTableSchema.getTableHash();
                field = customTableSchema.getField();
                expression = String.format("`%s`.`%s`", customTableSchema.getTableHash(), customTableSchema.getField());
            }
            // select e.g. `tableHash`.`field` AS fieldHash
            customQuerySqlQueryContext.getSelectColumns().add(String.format("%s AS %s", expression, fieldHash));
            // set ColumnExpMap
            customQuerySqlQueryContext.getColumnExpressionMap().put(dimension.getFieldHash(), expression);
            // group by e.g. `tableHash`.`field`
            customQuerySqlQueryContext.getGroupByColumns().add(expression);
            // result
            customQuerySqlQueryContext.getResultColumns().add(QueryParam.ResultColumn.builder()
                    .field(field)
                    .fieldHash(fieldHash)
                    .columnType(columnType)
                    .tableHash(tableHash)
                    .build());
        });
    }
}
